﻿using Plugins.Base.Common;
using Plugins.Common;
using Plugins.UserControls;
using TechnicalIndicators.DateBased;

namespace TrixPlugin.Common
{
	internal class DirectionChangeProcessor : IDecisionEngineStateProcessor
	{
		#region Attributes

		private readonly HourSelectorData _hourSettings;
		private readonly StrategyControlData _strategySettings;
		private readonly Trix _trixGenerator;
		private readonly DecisionEngineData _data;
		private readonly OperationManager _operationManager;

		#endregion

		#region Public Methods

		public DirectionChangeProcessor(Trix trixGenerator, StrategyControlData strategySettings, HourSelectorData hourSettings, DecisionEngineData data, OperationManager operationManager)
		{
			_trixGenerator = trixGenerator;
			_strategySettings = strategySettings;
			_hourSettings = hourSettings;
			_data = data;
			_operationManager = operationManager;
		}

		public DecisionEngineStateBase ProcessWaitingDirection()
		{
			DecisionEngineStateBase result = null;

			if (_data.LastQuotation.Date.TimeOfDay > _hourSettings.LastOpen)
			{
				result = DecisionEngineState.DayClosed;
			}
			else if (_trixGenerator.LastValue != null && _data.PreviousTrix != null)
			{
				if (_trixGenerator.LastValue.Y > _data.PreviousTrix)
				{
					_operationManager.OpenLongPossition(_strategySettings.Volume);
					result = DecisionEngineState.OnLongPossition;
				}
				else if (_trixGenerator.LastValue.Y < _data.PreviousTrix)
				{
					_operationManager.OpenShortPossition(_strategySettings.Volume);
					result = DecisionEngineState.OnShortPossition;
				}
			}

			return result;
		}

		public DecisionEngineStateBase ProcessOnLongPossition()
		{
			DecisionEngineStateBase result = null;

			if (_data.LastQuotation.Date.TimeOfDay >= _hourSettings.ForcedCloseTime)
			{
				_operationManager.CloseLongPossition();
				result = DecisionEngineState.DayClosed;
			}
			else if (_trixGenerator.LastValue.Y < _data.PreviousTrix)
			{
				_operationManager.CloseLongPossition();
				_operationManager.OpenShortPossition(_strategySettings.Volume);
				result = DecisionEngineState.OnShortPossition;
			}
			else if (_strategySettings.StopLoss > 0 && _operationManager.CurrentOperation.BuyPrice - _data.LastQuotation.Buyers[0].Value > _strategySettings.StopLoss)
			{
				_operationManager.CloseLongPossition();
				result = DecisionEngineState.WaitingDirection;
			}

			return result;
		}

		public DecisionEngineStateBase ProcessOnShortPossition()
		{
			DecisionEngineStateBase result = null;

			if (_data.LastQuotation.Date.TimeOfDay >= _hourSettings.ForcedCloseTime)
			{
				_operationManager.CloseShortPossition();
				result = DecisionEngineState.DayClosed;
			}
			else if (_trixGenerator.LastValue.Y > _data.PreviousTrix)
			{
				_operationManager.CloseShortPossition();
				_operationManager.OpenLongPossition(_strategySettings.Volume);
				result = DecisionEngineState.OnLongPossition;
			}
			else if (_strategySettings.StopLoss > 0 && _data.LastQuotation.Sellers[0].Value - _operationManager.CurrentOperation.SellPrice > _strategySettings.StopLoss)
			{
				_operationManager.CloseShortPossition();
				result = DecisionEngineState.WaitingDirection;
			}

			return result;
		}

		#endregion
	}
}
